package gamejam.game;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.geom.Rectangle2D;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;

import redsoxfan.gamejam.base.GameResource;

public class Map {
	public static final int TILE_SIZE = 50;
	private Tile[][] tiles;
	private ArrayList<Tile> leftCollisions = new ArrayList<Tile>(), rightCollisions = new ArrayList<Tile>(),
			topCollisions = new ArrayList<Tile>(), bottomCollisions = new ArrayList<Tile>();
	private Point start;
	private Point finish;
	private Rectangle2D.Double viewport;
	private Tile finishTile;
	public Map(URL map, int width, int height) throws Exception {
		viewport = new Rectangle2D.Double(0, 0, 800, 600);
		BufferedReader br = new BufferedReader(new InputStreamReader(map.openStream()));
		int rows = Integer.parseInt(br.readLine());
		int cols = Integer.parseInt(br.readLine());
		tiles = new Tile[rows][cols];
		for (int r=0; r<rows; r++) {
			char[] row = br.readLine().toLowerCase().toCharArray();
			for (int c=0; c<Math.min(row.length, cols); c++) {
				char spot = row[c];
				if (spot == 's') {
					start = new Point(c, r);
					center(start.x * TILE_SIZE - TILE_SIZE / 2, start.y * TILE_SIZE + TILE_SIZE / 2);
				} else if (spot == 'f') {
					finish = new Point(c, r);
					finishTile = new Tile(GameResource.loadImage("/gamejam/game/finish_sprite.png", TILE_SIZE, TILE_SIZE), TILE_SIZE * c, TILE_SIZE * r);
				} else if (spot == 'x') {
					tiles[r][c] = new Tile(GameResource.loadImage("/gamejam/game/platform_sprite.png", TILE_SIZE, TILE_SIZE), TILE_SIZE * c, TILE_SIZE * r);
				}
			}
		}
		br.close();
		if (start == null)
			throw new Exception("No start spot (s) in the map file");
		if (finish == null)
			throw new Exception("No finish spot (f) in the map file");
		
		for (int r=0; r<rows; r++) {
			for (int c=1; c<cols; c++) {
				if (tiles[r][c-1] == null && tiles[r][c] != null) {
					rightCollisions.add(tiles[r][c]);
				}
			}
		}
		for (int r=0; r<rows; r++) {
			for (int c=0; c<cols - 1; c++) {
				if (tiles[r][c+1] == null && tiles[r][c] != null) {
					leftCollisions.add(tiles[r][c]);
				}
			}
		}
		for (int c=0; c<rows; c++) {
			for (int r=0; r<cols - 1; r++) {
				if (tiles[r+1][c] == null && tiles[r][c] != null) {
					topCollisions.add(tiles[r][c]);
				}
			}
		}
		for (int c=0; c<rows; c++) {
			for (int r=1; r<cols; r++) {
				if (tiles[r-1][c] == null && tiles[r][c] != null) {
					bottomCollisions.add(tiles[r][c]);
				}
			}
		}
	}
	public void center(int cx, int cy) {
		viewport.x = Math.round(Math.min(Math.max(0, cx - viewport.width / 2), tiles.length * TILE_SIZE - viewport.width));
		viewport.y = Math.round(Math.min(Math.max(0, cy - viewport.height / 2), tiles[0].length * TILE_SIZE - viewport.height));
	}
	public void draw(Graphics g) {
		for (Tile[] row : tiles)
			for (Tile tile: row)
				if (tile != null && tile.getBounds().intersects(viewport))
					tile.draw(g, (int) viewport.x, (int) viewport.y);
		if (finishTile.getBounds().intersects(viewport))
			finishTile.draw(g, (int) viewport.x, (int) viewport.y);
	}
	public Point getFinishPosition() {
		return new Point(finish.x * TILE_SIZE, finish.y * TILE_SIZE);
	}
	public Point getStartPosition() {
		return new Point(start.x * TILE_SIZE, start.y * TILE_SIZE);
	}
	public Rectangle2D getViewport() {
		return viewport;
	}
	public boolean isTopCollision(Rectangle2D rect){
		for(Tile mapRect : topCollisions){
			if(rect.intersects(mapRect.getBounds())) return true;
		}
		return false;
	}
	public boolean isLeftCollision(Rectangle2D rect){
		for(Tile mapRect : leftCollisions){
			if(rect.intersects(mapRect.getBounds())) return true;
		}
		return false;
	}
	public boolean isRightCollision(Rectangle2D rect){
		for(Tile mapRect : rightCollisions){
			if(rect.intersects(mapRect.getBounds())) return true;
		}
		return false;
	}
	public boolean isBottomCollision(Rectangle2D rect){
		for(Tile mapRect : bottomCollisions){
			if(rect.intersects(mapRect.getBounds())) return true;
		}
		return false;
	}
}